#pragma once
#include <d3dx9.h>
#include <vector>
#include "ColourHelper.h"
#include "Vertex.h"
#include <assert.h>

using namespace std;



#define NULL 0
#define SCREENWIDTH 800
#define SCREENHEIGHT 600

class SimpleRender
{
public:

	// make this a singleton
	static SimpleRender& Get()
	{
		if(!pRender)
		{
			pRender = new SimpleRender();

			//pRender->Init();
		}

		return *pRender;
	}

	static void SimpleRender::Kill()
	{
		if(pRender)
		{
			delete pRender;

			pRender = NULL;
		}
	}

	struct Vertex
	{
		Vertex()
		{
			Position.x = 0;
			Position.y = 0;
			Position.z = 0;
			col = 0;
		}

		D3DXVECTOR3 Position;
		DWORD   col;

		static int Format()
		{
			return (D3DFVF_XYZ|D3DFVF_DIFFUSE);
		}
	};

	// int everything
	void Init();
	void ClearScreen(D3DXCOLOR backGroundColor);
	void ClearScreen();

	// projection types
	void Set3DProjection();
	void Set2DProjection();

	// draw 2D shapes
	void DrawQuad2D(signed int x, signed int y, signed int width, signed int height, D3DCOLOR c);

	// render user geometry
	void Render(const VERTEXPOSCOL& rVerts, unsigned int PrimCount,D3DPRIMITIVETYPE ePrimType);
	void Render(const Vertex& rVerts, unsigned int PrimCount,D3DPRIMITIVETYPE ePrimType);

	LPDIRECT3D9             g_pD3D; // Used to create the D3DDevice
	LPDIRECT3DDEVICE9       g_pd3dDevice; // Our rendering device

	LPDIRECT3DDEVICE9 GetDevice() { return g_pd3dDevice; }
	HWND& GetWindow() { return hWnd; }
	HINSTANCE& GetWindowInst() { return hInst; }

	// required for window creation
	static LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
	{
		switch( msg )
		{
		case WM_DESTROY:
			PostQuitMessage( 0 );
			return 0;
		}

		return DefWindowProc( hWnd, msg, wParam, lParam );
	}


	~SimpleRender(void);

	// Font rendering
	void DrawText(signed int x, signed int y, const char *Text, D3DCOLOR c);
	void DrawText(signed int x, signed int y, const char *Text);
	void SetFont(const char *Name, unsigned int Size);

	// convert char array to LPCWSTR (for loading meshes/textures
	static LPCWSTR char2wstr(const char* in);

	struct FontData
	{
		FontData();
		~FontData();
		unsigned int Size;
		unsigned int Flags;

		char* Name;

		ID3DXFont*  pFont; 

		void Init(const char* name, unsigned int size, unsigned int flags);
		void Draw(const char* Text,const RECT& r,D3DCOLOR c) const;

	private:

		void Reset();
	};



private:
	// simple render singleton
	static SimpleRender* pRender;

	// matrices
	D3DXMATRIXA16 matProj; // current projection matrix

	// our window
	WNDCLASSEX wc;
	HWND hWnd;
	HINSTANCE hInst;

	// create the window and register it with new D3D device
	void CreateD3DWindow();
	// create and init the D3D device
	HRESULT InitD3D( HWND hWnd ); 

	// font rendering
	void CleanupFonts();
	typedef vector<FontData*> FontList;
	FontList mFontList;
	FontData *CurrentFont;

	// 2Dscaling
	float scale2DX;
	float scale2DY;

	// private contructor
	SimpleRender(void)
	{
		pRender = NULL;
		g_pd3dDevice = NULL;
		g_pD3D = NULL;
		//	wc = NULL;

	}

	// release devices
	VOID CleanupD3D()
	{
		// release D3D devices
		if( g_pd3dDevice != NULL )
			g_pd3dDevice->Release();

		if( g_pD3D != NULL )
			g_pD3D->Release();

		// unregister Window
		UnregisterClass( L"D3D Tutorial", wc.hInstance );
	}
};
